<?php

namespace services\clinic;

use Yii;
use common\components\Service;
use common\helpers\CommonHelper;
use common\models\clinic\Clinic;
use common\models\clinic\Doctor;
use common\models\clinic\Project as ClinicProject;
use common\models\clinic\UserTreatment;
use common\models\marketing\OutpatientType;
use common\models\patient\Consumption;
use common\models\patient\User;
use common\models\patient\RevisitingRecord;
use common\models\statistics\StatisticsDoctor;
use api\modules\v1\forms\clinic\DoctorForm;

/**
 * Class ClinicDoctorService
 * @package services\clinic
 */
class ClinicDoctorService extends Service
{
    /**
     * 医生列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0)
    {
        $query = Doctor::find()->alias('a')
            ->select(['a.*', 'b.name clinic_name'])
            ->leftJoin(Clinic::tableName().' b', 'b.id = a.clinic_id')
            ->where([
                'a.status' => [Doctor::STATUS_INVALID, Doctor::STATUS_ENABLE],
                'a.project_id' => Yii::$app->params['project_id'],
            ]);

        $order = ['a.status' => SORT_DESC, 'a.id' => SORT_ASC];

        $data = $this->getListPageRes($query, $page, $pageSize, $order);

        // 格式化
        $list = [];
        foreach ($data['list'] as $row) {
            $list[] = [
                'id' => $row['id'],
                'project_id' => $row['project_id'],
                'clinic_id' => $row['clinic_id'],
                'name' => $row['name'],
                'clinic_name' => $row['clinic_name'] ?: '',
                'status' => $row['status'],
                'status_str' => Doctor::$statuss[$row['status']],
            ];
        }
        $data['list'] = $list;

        return $data;
    }

    /**
     * 医生详情
     *
     * @param int $id
     * @return array
     */
    public function getDoctorInfo(int $id = 0)
    {
        $doctor = Doctor::findOne($id);

        // 获取筛选条件
        $params = [
            'get_clinic' => 1,
        ];

        $condition = Yii::$app->services->patientUser->getConditionList($params, Yii::$app->params['project_id']);

        $doctorList = Doctor::find()
            ->where([
                'project_id' => Yii::$app->params['project_id'],
                'clinic_id' => array_column($condition['clinic_list'], 'id'),
                'status' => Doctor::STATUS_ENABLE
            ])
            ->indexBy('clinic_id')
            ->asArray()
            ->all();
        foreach ($condition['clinic_list'] as &$row) {
            $row['disabled'] = isset($doctorList[$row['id']]) ? 1 : 0;
        }

        return [
            'id' => $doctor->id ?? 0,
            'clinic_id' => $doctor->clinic_id ?? 0,
            'name' => $doctor->name ?? '',
            'status' => $doctor->status ?? Doctor::STATUS_ENABLE,
            'condition' => [
                'clinic_list' => $condition['clinic_list'],
            ],
        ];
    }

    /**
     * 新增医生
     *
     * @param array $params
     * @return array
     * @throws \Exception
     */
    public function create(array $params)
    {
        $model = new DoctorForm();
        $model->setScenario('create');
        $model->attributes = $params;
        if ($model->validate() === false) {
            throw new \Exception(CommonHelper::analyErr($model->getFirstErrors()));
        }

        // 1.新增医生
        $doctor = new Doctor();
        $doctor->project_id = Yii::$app->params['project_id'];
        $doctor->clinic_id = $model->clinic_id ?: 0;
        $doctor->name = $model->name;
        $doctor->status = $model->status;
        $doctor->saveAndCheckResult();

        return ['id' => $doctor->id];
    }

    /**
     * 编辑医生
     *
     * @param array $params
     * @return array
     * @throws \Exception
     */
    public function edit(array $params)
    {
        $model = new DoctorForm();
        $model->setScenario('edit');
        $model->attributes = $params;
        if ($model->validate() === false) {
            throw new \Exception(CommonHelper::analyErr($model->getFirstErrors()));
        }

        // 1.更新医生
        $doctor = $model->getDoctorInfo();
        $doctor->clinic_id = $model->clinic_id ?: 0;
        $doctor->name = $model->name;
        $doctor->status = $model->status;
        $doctor->saveAndCheckResult();

        return ['id' => $doctor->id];
    }

    /**
     * 医生报表
     *
     * @param array $params
     * @return bool
     * @throws \yii\db\Exception
     */
    public function createReport(array $params = [])
    {
        set_time_limit(0);
        ini_set('memory_limit', '4G');

        $params['start_time'] = $params['start_time'] ?? '';
        $params['end_time'] = $params['end_time'] ?? '';
        // 类型【1日期、2上旬(1-10)、3中旬(1-20)、4全月】
        $params['type'] = $params['type'] ?? 1;
        if (empty($params['start_time']) || empty($params['end_time'])) {
            throw new \Exception('时间段参数错误');
        }

        $doctorList = Doctor::find()
            ->select(['id', 'project_id', 'clinic_id'])
            ->where([
                'status' => Doctor::STATUS_ENABLE,
            ])
            ->andWhere(['>', 'clinic_id', 0])
            ->asArray()
            ->all();

        $projectIds = array_column($doctorList, 'project_id');
        $clinicIds = array_column($doctorList, 'clinic_id');

        $data = [];

        $patientCardIds = [];// 总cardID【统计合个患者收入】

        // 挂号人数【初次挂号时间】
        // 流失人数【挂号人数范围就诊类型为流失】
        $firstQuery = $this->createUserQuery($projectIds, $clinicIds);
        $firstList = $firstQuery
            ->select([
                'id', 'project_id', 'patient_card_id', 'clinic_id', 'outpatient_type_id'
            ])
            ->andWhere(['>=', 'reg_time', strtotime($params['start_time'])])
            ->andWhere(['<=', 'reg_time', strtotime($params['end_time'].' 23:59:59')])
            ->asArray()
            ->all();
        $patientCardIds = array_merge($patientCardIds, array_column($firstList, 'patient_card_id'));

        // 初诊人数【上次到诊日期】
        // 复诊人数
        // 总就诊人数【初诊+复诊】
        $againQuery = $this->createRevistingRecordQuery($projectIds, $clinicIds);
        $againList = $againQuery
            ->select([
                'a.project_id', 'a.patient_card_id', 'a.clinic_id', 'b.outpatient_type_id'
            ])
//            ->andWhere([
//                'b.outpatient_type_id' => [OutpatientType::ID_FIRST_VISIT, OutpatientType::ID_CONTINUE_VISIT]
//            ])
            ->andWhere(['>=', 'a.revisting_time', strtotime($params['start_time'])])
            ->andWhere(['<=', 'a.revisting_time', strtotime($params['end_time'].' 23:59:59')])
            ->asArray()
            ->all();
        $againPatientCardIds = array_column($againList, 'patient_card_id');
        $patientCardIds = array_merge($patientCardIds, $againPatientCardIds);

        // 数据处理
        foreach ($firstList as $row) {
            // 挂号人数
            $data[$row['project_id']][$row['clinic_id']]['reg_num'] =
                $data[$row['project_id']][$row['clinic_id']]['reg_num'] ?? 0;

            $data[$row['project_id']][$row['clinic_id']]['reg_num']++;

            // 流失人数
            if ($row['outpatient_type_id'] == OutpatientType::ID_LOSS) {
                $data[$row['project_id']][$row['clinic_id']]['loss_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['loss_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['loss_num']++;
            }

            // 挂号患者IDs
            $data[$row['project_id']][$row['clinic_id']]['reg_user_card_id'] =
                $data[$row['project_id']][$row['clinic_id']]['reg_user_card_id'] ?? [];

            $data[$row['project_id']][$row['clinic_id']]['reg_user_card_id'][] = $row['patient_card_id'];
        }
        unset($firstList);

        foreach ($againList as $row) {
            if ($row['outpatient_type_id'] == OutpatientType::ID_FIRST_VISIT) {
                // 初诊人数
                $data[$row['project_id']][$row['clinic_id']]['first_reg_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['first_reg_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['first_reg_num']++;

                // 初诊患者cardIDs
                $data[$row['project_id']][$row['clinic_id']]['first_reg_user_card_id'] =
                    $data[$row['project_id']][$row['clinic_id']]['first_reg_user_card_id'] ?? [];

                $data[$row['project_id']][$row['clinic_id']]['first_reg_user_card_id'][] = $row['patient_card_id'];
            } elseif ($row['outpatient_type_id'] == OutpatientType::ID_CONTINUE_VISIT) {
                // 复诊人数
                $data[$row['project_id']][$row['clinic_id']]['again_reg_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['again_reg_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['again_reg_num']++;

                // 复诊患者cardIDs
                $data[$row['project_id']][$row['clinic_id']]['again_reg_user_card_id'] =
                    $data[$row['project_id']][$row['clinic_id']]['again_reg_user_card_id'] ?? [];

                $data[$row['project_id']][$row['clinic_id']]['again_reg_user_card_id'][] = $row['patient_card_id'];
            }

            // 总就诊人数
            $data[$row['project_id']][$row['clinic_id']]['total_num'] =
                $data[$row['project_id']][$row['clinic_id']]['total_num'] ?? 0;

            $data[$row['project_id']][$row['clinic_id']]['total_num']++;
        }
        unset($againList);

        // 挂号收入
        // 初诊收入
        // 复诊收入
        $consumptionList = Consumption::find()
            ->select(['id', 'project_id', 'clinic_id', 'patient_card_id', 'SUM(reality_money) money'])
            ->where([
                'project_id' => $projectIds,
                'patient_card_id' => $patientCardIds,
                'clinic_id' => $clinicIds,
            ])
            ->andWhere(['>=', 'clinic_time', strtotime($params['start_time'])])
            ->andWhere(['<=', 'clinic_time', strtotime($params['end_time'].' 23:59:59')])
            ->groupBy('project_id,clinic_id,patient_card_id')
            ->asArray()
            ->all();
        foreach ($consumptionList as $row) {
            // 挂号收入
            $data[$row['project_id']][$row['clinic_id']]['reg_user_card_id'] =
                $data[$row['project_id']][$row['clinic_id']]['reg_user_card_id'] ?? [];
            if (in_array($row['patient_card_id'], $data[$row['project_id']][$row['clinic_id']]['reg_user_card_id'])) {
                $data[$row['project_id']][$row['clinic_id']]['reg_money'] =
                    $data[$row['project_id']][$row['clinic_id']]['reg_money'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['reg_money'] += $row['money'];
            }

            // 初诊收入
            $data[$row['project_id']][$row['clinic_id']]['first_reg_user_card_id'] =
                $data[$row['project_id']][$row['clinic_id']]['first_reg_user_card_id'] ?? [];
            if (in_array($row['patient_card_id'], $data[$row['project_id']][$row['clinic_id']]['first_reg_user_card_id'])) {
                $data[$row['project_id']][$row['clinic_id']]['first_money'] =
                    $data[$row['project_id']][$row['clinic_id']]['first_money'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['first_money'] += $row['money'];
            }

            // 复诊收入
            $data[$row['project_id']][$row['clinic_id']]['again_reg_user_card_id'] =
                $data[$row['project_id']][$row['clinic_id']]['again_reg_user_card_id'] ?? [];
            if (in_array($row['patient_card_id'], $data[$row['project_id']][$row['clinic_id']]['again_reg_user_card_id'])) {
                $data[$row['project_id']][$row['clinic_id']]['again_money'] =
                    $data[$row['project_id']][$row['clinic_id']]['again_money'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['again_money'] += $row['money'];
            }

            // 总收入
            if (in_array($row['patient_card_id'], $againPatientCardIds)) {
                $data[$row['project_id']][$row['clinic_id']]['total_money'] =
                    $data[$row['project_id']][$row['clinic_id']]['total_money'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['total_money'] += $row['money'];
            }
        }
        unset($consumptionList);

        // 308统计
        $traementQuery = $this->getClinicGroupList($projectIds);
        $traementList = $traementQuery
            ->andWhere(['a.type' => [UserTreatment::TYPE_TREAT, UserTreatment::TYPE_ADD, UserTreatment::TYPE_REDUCE]])
            ->andWhere(['>=', 'a.recently_clinic_time', strtotime($params['start_time'])])
            ->andWhere(['<=', 'a.recently_clinic_time', strtotime($params['end_time'].' 23:59:59')])
            ->asArray()
            ->all();
        foreach ($traementList as $row) {
            // 操作数【治疗/购买/退费】
            $clinicNum = $row['recently_clinic_num'] + $row['recently_surplus_num'];

            // 人次
            $patientTimesNum = $row['times_num'];

            // 人数
            $patientNum = $row['patient_num'];

            if ($row['type'] == UserTreatment::TYPE_TREAT) {// 治疗
                // 308治疗量
                $data[$row['project_id']][$row['clinic_id']]['tmp_treament_clinic_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['tmp_treament_clinic_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['tmp_treament_clinic_num'] += $clinicNum;

                // 308治疗人数
                $data[$row['project_id']][$row['clinic_id']]['tmp_treament_patient_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['tmp_treament_patient_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['tmp_treament_patient_num'] += $patientNum;
            } elseif ($row['type'] == UserTreatment::TYPE_ADD) {// 购买
                // 308购买量
                $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] += $clinicNum;

                // 308购买人数
                $data[$row['project_id']][$row['clinic_id']]['tmp_buy_patient_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['tmp_buy_patient_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['tmp_buy_patient_num'] += $patientNum;
            }  else {// 退费
                // 308购买量
                $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] =
                    $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] ?? 0;

                $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] -= $clinicNum;
            }
        }

        $column = [
            'project_id', 'clinic_doctor_id', 'clinic_id', 'type', 'start_time', 'end_time',
            'reg_num', 'reg_money', 'reg_avg_money', 'loss_num', 'loss_rate',
            'first_reg_num', 'first_money', 'first_avg_money',
            'again_reg_num', 'again_money', 'again_avg_money',
            'total_num', 'total_money', 'total_avg_money',
            'tmp_buy_clinic_num', 'tmp_buy_patient_num',  'tmp_buy_avg_num',
            'tmp_treament_clinic_num', 'tmp_treament_patient_num', 'tmp_treament_avg_num',
            'created_at', 'updated_at'
        ];

        $time = time();
        $insertData = [];
        foreach ($doctorList as $row) {
            // 挂号
            $regNum = $data[$row['project_id']][$row['clinic_id']]['reg_num'] ?? 0;
            $regMoney = $data[$row['project_id']][$row['clinic_id']]['reg_money'] ?? 0;
            $regAvgMoney = $regNum > 0
                ? number_format($regMoney / $regNum, 2, '.', '') : 0;
            // 流失
            $lossNum = $data[$row['project_id']][$row['clinic_id']]['loss_num'] ?? 0;
            $lossRate = $regNum > 0
                ? number_format($lossNum / $regNum, 2, '.', '') : 0;
            // 初诊
            $firstRegNum = $data[$row['project_id']][$row['clinic_id']]['first_reg_num'] ?? 0;
            $firstMoney = $data[$row['project_id']][$row['clinic_id']]['first_money'] ?? 0;
            $firstAvgMoney = $firstRegNum > 0
                ? number_format($firstMoney / $firstRegNum, 2, '.', '') : 0;
            // 复诊
            $againRegNum = $data[$row['project_id']][$row['clinic_id']]['again_reg_num'] ?? 0;
            $againMoney = $data[$row['project_id']][$row['clinic_id']]['again_money'] ?? 0;
            $againAvgMoney = $againRegNum > 0
                ? number_format($againMoney / $againRegNum, 2, '.', '') : 0;
            // 总
            $totalNum = $data[$row['project_id']][$row['clinic_id']]['total_num'] ?? 0;
            $totalMoney = $data[$row['project_id']][$row['clinic_id']]['total_money'] ?? 0;
            $totalAvgMoney = $totalNum > 0
                ? number_format($totalMoney / $totalNum, 2, '.', '') : 0;
            // 308购买
            $tmpBuyClinicNum = $data[$row['project_id']][$row['clinic_id']]['tmp_buy_clinic_num'] ?? 0;
            $tmpBuyPatientNum = $data[$row['project_id']][$row['clinic_id']]['tmp_buy_patient_num'] ?? 0;
            $tmpBuyAvgNum = $tmpBuyPatientNum > 0
                ? number_format($tmpBuyClinicNum / $tmpBuyPatientNum, 2, '.', '') : 0;
            // 308治疗
            $tmpTreamentClinicNum = $data[$row['project_id']][$row['clinic_id']]['tmp_treament_clinic_num'] ?? 0;
            $tmpTreamentPatientNum = $data[$row['project_id']][$row['clinic_id']]['tmp_treament_patient_num'] ?? 0;
            $tmpTreamentAvgNum = $tmpTreamentPatientNum > 0
                ? number_format($tmpTreamentClinicNum / $tmpTreamentPatientNum, 2, '.', '') : 0;

            $insertData[] = [
                $row['project_id'],
                $row['id'],
                $row['clinic_id'],
                $params['type'],
                $params['start_time'],
                $params['end_time'],
                $regNum,
                $regMoney,
                $regAvgMoney,
                $lossNum,
                $lossRate,
                $firstRegNum,
                $firstMoney,
                $firstAvgMoney,
                $againRegNum,
                $againMoney,
                $againAvgMoney,
                $totalNum,
                $totalMoney,
                $totalAvgMoney,
                $tmpBuyClinicNum,
                $tmpBuyPatientNum,
                $tmpBuyAvgNum,
                $tmpTreamentClinicNum,
                $tmpTreamentPatientNum,
                $tmpTreamentAvgNum,
                $time,
                $time,
            ];
        }

        Yii::$app->db->createCommand()->batchInsert(
            StatisticsDoctor::tableName(),
            $column,
            $insertData
        )->execute();

        return true;
    }

    /**
     * 患者Query
     *
     * @param $projectIds
     * @param $clinicIds
     * @return \yii\db\ActiveQuery
     */
    public function createUserQuery($projectIds, $clinicIds)
    {
        $query = User::find()
            ->where([
                'project_id' => $projectIds,
                'clinic_id' => $clinicIds,
                'status' => User::STATUS_ENABLE,
            ]);
            // ->groupBy('project_id,clinic_id');

        return $query;
    }

    /**
     * 患者上次来院记录Query
     *
     * @param $projectIds
     * @param $clinicIds
     * @return \yii\db\ActiveQuery
     */
    public function createRevistingRecordQuery($projectIds, $clinicIds)
    {
        $query = RevisitingRecord::find()->alias('a')
            ->innerJoin(User::tableName().' b', 'b.patient_card_id = a.patient_card_id AND b.project_id = a.project_id')
            ->where([
                'a.project_id' => $projectIds,
                'a.clinic_id' => $clinicIds,
            ])
            ->groupBy('a.project_id,a.clinic_id,a.patient_card_id');

        return $query;
    }


    /**
     * 获取分组信息
     *
     * @param array $params
     * @return array|\yii\db\ActiveRecord[]
     */
    /**
     * 分组信息
     *
     * @param $projectIds
     * @return \yii\db\ActiveQuery
     */
    public function getClinicGroupList($projectIds)
    {
        $query = UserTreatment::find()->alias('a')
            ->select([
//                'a.id',
                'a.project_id',
                'a.clinic_id',
                'a.type',
                'COUNT(a.patient_card_id) AS times_num',// 人次
                'COUNT(DISTINCT a.patient_card_id) AS patient_num',// 人数
                'SUM(a.recently_clinic_num) AS recently_clinic_num',
                'SUM(a.recently_surplus_num) AS recently_surplus_num',
            ])
            ->innerJoin(ClinicProject::tableName() . ' AS b', 'b.id = a.clinic_project_id')
            ->where([
                'a.project_id' => $projectIds,
                'b.template' => ClinicProject::TEMPLATE_308,
            ])
            ->groupBy('a.project_id,a.clinic_id,a.type');

        return $query;
    }
}
